﻿/****************************************************************
*   作者：Schme
*   CLR版本：4.0.30319.42000
*   创建时间：2017/4/19 18:34:01
*   2017
*   描述说明：
*
*   修改历史：
*
*
*****************************************************************/
using Abp.Configuration;
using Abp.Domain.Repositories;
using Abp.Domain.Services;
using Abp.Domain.Uow;
using Abp.Extensions;
using Abp.Timing;
using Microsoft.EntityFrameworkCore;
using Mt.Site.Core.Members.Values;
using Mt.Site;
using Mt.Site.Core.Configuration;
using System;
using System.Linq;
using System.Text.RegularExpressions;
using System.Threading.Tasks;

namespace Mt.Site.Core.Members
{
    public class MemberManager: DomainService,IMemberManager
    {
        private readonly IRepository<Member, Guid> _memberRepository;
        private readonly IRepository<MemberInfo, Guid> _memberInfoRepository;
        private readonly ISettingManager _settingManager;

        public MemberManager(
            IRepository<Member, Guid> memberRepository,
            IRepository<MemberInfo, Guid> memberInfoRepository,
            ISettingManager settingManager)
        {
            _memberRepository = memberRepository;
            _memberInfoRepository = memberInfoRepository;
            _settingManager = settingManager;
        }

        #region Member
        /// <summary>
        /// 登陆信息 
        /// 账号冻结：启用账号锁定（连续8次登陆失败，锁定20分钟）  
        /// </summary>
        /// <param name="userName">用户名</param>
        /// <param name="password">密码</param>
        /// <returns>0：账号或密码错误；1：正常；2：登陆失败</returns>
        public async Task<LoginResult> LoginInfo(string userName, string password, bool isPersistent)
        {
            var result = new LoginResult { ResultType = ResultType.InvalidParameter };

            if (!userName.IsNullOrWhiteSpace() && !password.IsNullOrWhiteSpace())
            {
                var member = await _memberRepository.FirstOrDefaultAsync(
                                t => t.Email == userName || t.LoginName == userName);     // 用户名查找
                if (member != null)
                {
                    result.ResultType = await CheckLoginResult(password, member);
                    if (result.ResultType == ResultType.Success)
                    {
                        string valExp = await SettingManager.GetSettingValueAsync(MtAppSettings.Security.UserPwdRegex);
                        if (!Regex.IsMatch(password, valExp))
                        {
                            result.ResultType = ResultType.Simple;
                        }

                        result.MemberCacheItem = GetMemberCacheItem(member, isPersistent);
                    }
                }
            }

            return result;
        }

        private async Task<ResultType> CheckLoginResult(string password, Member member)
        {
            if (!member.IsActive)
            {
                return ResultType.Fail;  // 账号被封禁
            }
            else if (member.FreezeEndTime != null && member.FreezeEndTime.Value > Clock.Now)
            {
                return ResultType.Frozen;   // 账号被暂时冻结
            }
            else if (member.Password.ToLower() == password.ToMd5().ToLower())
            {
                member.LastLoginTime = Clock.Now;
                member.LoginCount++;
                member.FailLoginCount = 0;
                if (member.VerificationCode.IsNullOrEmpty())
                {
                    member.VerificationCode = Guid.NewGuid().ToString();
                }
                await UpdateMemberAsync(member);
                return ResultType.Success;
            }
            else
            {
                member.FailLoginCount++;
                int maxFailCount = await SettingManager.GetSettingValueAsync<int>(MtAppSettings.Security.UserMaxFailCount);
                if (member.FailLoginCount >= maxFailCount)
                {
                    member.FailLoginCount = 0;
                    int freezeTime = await SettingManager.GetSettingValueAsync<int>(MtAppSettings.Security.UserFreezeTime);
                    member.FreezeEndTime = Clock.Now.AddMinutes(freezeTime);
                }
                await UpdateMemberAsync(member);
                return ResultType.InvalidParameter;
            }
        }

        private MemberCacheItem GetMemberCacheItem(Member member, bool isPersistent)
        {
            // 会员基本信息
            var memberCacheItem = new MemberCacheItem
            {
                MemberID = member.Id,
                LoginName = member.LoginName,
                Email = member.Email,
                VerificationCode = member.VerificationCode,
                IsPersistent = isPersistent
            };

            return memberCacheItem;
        }

        public async Task<MemberCacheItem> GetMemberCacheItemById(MemberCookieItem member)
        {
            var memberData = await _memberRepository.FirstOrDefaultAsync(member.UserId);
            if (memberData != null)
            {
                return GetMemberCacheItem(memberData, member.P);
            }
            return null;
        }

        /// <summary>
        /// 注册会员
        /// </summary>
        /// <param name="input"></param>
        /// <returns></returns>
        public async Task<Guid> RegisterMember(Member input)
        {
            return await _memberRepository.InsertAndGetIdAsync(input);
        }

        /// <summary>
        /// 删除会员
        /// </summary>
        /// <param name="ID"></param>
        /// <returns></returns>
        public async Task DeleteMember(Guid ID)
        {
            await _memberInfoRepository.DeleteAsync(q => q.MemberID == ID);
            await _memberRepository.DeleteAsync(ID);
        }

        /// <summary>
        /// 重置密码111111
        /// </summary>
        /// <param name="ID"></param>
        /// <returns></returns>
        public async Task ResetPassword(Guid ID)
        {
            var member = await _memberRepository.GetAsync(ID);
            member.Password = "111111".ToMd5();
            member.VerificationCode = Guid.NewGuid().ToString();
        }
        
        public async Task UpdateMemberAsync(Member input)
        {
            //校验必填项等
            await _memberRepository.UpdateAsync(input);
        }
        #endregion

        #region MemberInfo

        /// <summary>
        /// 修改用户信息
        /// </summary>
        /// <param name="input"></param>
        /// <returns></returns>
        public async Task AddOrUpdateMemberInfoAsync(MemberInfo memberInfo)
        {
            if (memberInfo.IsTransient())
            {
                await _memberInfoRepository.InsertAsync(memberInfo);
            }
            else
            {
                await _memberInfoRepository.UpdateAsync(memberInfo);
            }
        }

        public async Task<MemberInfo> FirstOrDefaultMemberInfoAsync(Guid memberId,bool isMemberInfoLocalizated)
        {
            MemberInfo result;
            if (isMemberInfoLocalizated)
            {
                result = await _memberInfoRepository.FirstOrDefaultAsync(c => c.MemberID == memberId);
            }
            else
            {
                using (CurrentUnitOfWork.DisableFilter(
                    AbpDataFilters.MayHaveTenant,
                    AbpDataFilters.MustHaveTenant,
                    MtSiteConsts.AbpDataFilters.MustHaveLanguage))
                {
                    result = await _memberInfoRepository.FirstOrDefaultAsync(c => c.MemberID == memberId);
                }
            }

            if (result == null)
            {
                result = new MemberInfo
                {
                    MemberID = memberId
                };
            }

            return result;
        }
        #endregion



        /// <summary>
        /// 获取用户邮箱及用户是否被封禁
        /// </summary>
        /// <param name="EmailOrUsername"></param>
        /// <returns></returns>
        public async Task<EmailinfoDto> GetEamil2(string EmailOrUsername)
        {
            var query = _memberRepository.GetAll()
                                       .Where(m => (m.LoginName == EmailOrUsername || m.Email == EmailOrUsername))
                                       .OrderByDescending(item => item.IsActive);
            var info = await query.FirstOrDefaultAsync();

            if(info == null)
            {
                return null;
            }
            return new EmailinfoDto
            {
                IsActive = info.IsActive,
                Email = info.Email
            }; 
        }

        /// <summary>
        /// 获取Email
        /// </summary>
        /// <param name="EmailOrUsername"></param>
        /// <returns></returns>
        public async Task<string> GetEamil(string EmailOrUsername)
        {
            var query = from m in _memberRepository.GetAll()
                        where (m.LoginName == EmailOrUsername || m.Email == EmailOrUsername) && m.IsActive == true
                        select m.Email;
            var result = await query.FirstOrDefaultAsync();
            return result;
        }
    }
}
